CIST Solomonで解答を修正したことが分かるようにする
特定設問への解答が完了したあと、再度答案を決定したとき、修正することができる
考えられるユーザーの混乱
答案を修正できたのか?
ボタンが反応していないのか?
答案修正のPOSTリクエストへの200レスポンスが返ってきたとき、「答案の決定が完了しました」と表示する
document.querySelector(".examContentsButtonLayout")にp要素をappendChildすれば良い
ユーザーが問題を切り替えれば自動的に要素も消除されるので、問題ない
下記のような感じで良いか?
何度もテストできる環境があると楽である
code:example.js
const answerConfirmButtonContainer = document.querySelector(".examContentsButtonLayout");
if (!answerConfirmButtonContainer) return;
answerConfirmButtonContainer.addEventListener("click", () => {
const questionForm = answerConfirmButtonContainer.closest("form");
const messagePayload = {
type: "portalext_answer_fire",
form_action_target: questionForm.action
}
chrome.runtime.sendMessage(messagePayload);
});
const convertConfirmStatusToJapanese = (isCompleted) => {
if (isCompleted) {
return "答案の決定に成功しました。";
}
return "答案決定リクエストが失敗しました。開発者ツールを確認してください。";
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
const isConfirmMessage = request.type == "portalext_answer_confirm"
if (!isConfirmMessage) return;
const japaneseLabel = convertConfirmStateToJapanese(request.completed);
const answerCompletedLabel = document.createElement("p");
answerCompletedLabel.textContent = japaneseLabel;
answerConfirmButtonContainer.appendChild(answerCompletedLabel);
});
Statusを読むことはできるので、以下のように行う
1. Content Scriptからportalext_answer_fireをService Workerにpost
message structure
code:structure.ts
type PortalExtAnswerFireMessage = {
type: "portalext_answer_fire",
form_action_target: string
}
2. Service Workerで、イベントを受信する
3. イベントのform_action_targetをグローバル変数? current_watching_form_action_targetにセットする
グローバル変数ではなく、chrome.Storageを使わなければならない:
4. webRequest.onResponseStartedで、current_...と一致するものがあれば、portal_ext_answer_confirmイベントを送信する
Workerはおおよそできた気がするt6o_o6t.icon
code:worker.js
const sessionStorage = chrome.storage.session;
// memorize answer endpoint URL we have to track now
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type != "portalext_answer_fire") return;
// If the message is from not content script context
if (!session.tab) return;
// currentWatchingFormActionTarget should be managed by tab separately
const watchingTarget = {
currentWatchingFormActionTargetDict: {
}
}
sessionStorage.set(watchingTarget).then(() => {
console.debug([debug] currentWatchingFormActionTarget on ${sender.tab} was changed to ${request.form_action_target});
});
});
const processResponse = async (responseDetail) => {
// we expect type of formActionTarget is { tab in string: string } const entries = Object.entries(formActionTargetDict);
for (const entry of entries) {
if (formActionTarget != responseDetail.URL) continue;
// completed finding a tab which is waiting a response from responseDetail.URL
const messagePayload = {
type: "portal_ext_answer_confirm",
isCompleted: responseDetail.statusCode == 200
};
chrome.tabs.sendMessage(tabId, messagePayload);
console.debug([debug] tab: ${tabId}, status: ${messagePayload.isCompleted ? "completed" : "unknown"})
break;
};
}
chrome.webRequest.onResponseStarted.addListener((responseDetail) => {
processResponse(responseDetail);
});
Content Scriptも書けたt6o_o6t.icon
実験する
esbuildなどを組み込む必要が生じた
Chrome拡張機能はService Workerまわりのエラーが分かりにくいかもしれない
permissionsが不足しているからエラーが発生しているのか、など
上手く解決するフレームワークが欲されていそうt6o_o6t.icon
たとえばchrome.storageがundefinedである状態は不自然である
undefinedエラーをトリガーにmanifest.jsonでstorageが指定されているのか自動的に見に行ってくれるツールがあれば、すぐに気づけるかもしれない?
何もフィルターする必要がない場合もなぜか空オブジェクトを指定しなければならない
実験に使えるテストが少ない。。。t6o_o6t.icon
3つしかないので、大切に使う
さっそく1ミス
CBTから追い出されてしまった
テスト中に再読み込みをしてはいけない模様
この機能の開発は停止するt6o_o6t.icon
必要な機能であるが、将来的に使う可能性もある試験(残機)をこれ以上消費することに意義がない
featuresブランチを切った
テスト用のHTMLを作成すれば良い?
name属性やactionを模倣する
テスト用サーバーの作成
問題ページ(/question_body)
iframe埋め込み用ページ(/exam)
サーバー用フレームワーク
Express.js
routes
POST /action
bodyをconsole.logする
200を返却する
textは、<span>回答完了</span>
GET /exam
iframeを埋め込んだHTMLを返す
GET /question_body
/actionをactionとするform要素を持つ
/actionからのResponse内容をp要素内に書く
inline styleタグで、span要素にcolor: redを振る
おおよそサーバーを書けた
submitイベントをpreventDefaultできない?
submitしなければ良いのだろうか?
サーバーも実装できたt6o_o6t.icon
予期せぬバグがWorker側で多く起きたので、大きな収穫を得られた